<template>
  <div>
    <!-- 滚动侧栏学习工具 -->
    <!-- 内容区域 -->
    <div class="content">
      <div>
        content-0
      </div>
      <div>
        content-1
      </div>
      <div>
        content-2
      </div>
      <div>
        content-3
      </div>
      <div>
        content-4
      </div>
    </div>
    <!-- 导航区域 -->
    <ul class="navs">
      <li :class="{active: active===0}" @click="scrollTo(0)">
        content-0
      </li>
      <li :class="{active: active===1}" @click="scrollTo(1)">
        content-1
      </li>
      <li :class="{active: active===2}" @click="scrollTo(2)">
        content-2
      </li>
      <li :class="{active: active===3}" @click="scrollTo(3)">
        content-3
      </li>
      <li :class="{active: active===4}" @click="scrollTo(4)">
        content-4
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {},
  data() {
    return {
      active: 0 // 当前激活的导航索引
    }
  },
  methods: {
      // 滚动监听器
      onScroll() {
          // 获取所有锚点元素
          const navContents = document.querySelectorAll('.content div')
          // 所有锚点元素的 offsetTop
          const offsetTopArr = []
          navContents.forEach(item => {
              offsetTopArr.push(item.offsetTop)
          })

          // 获取当前文档流的 scrollTop
          const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
          // 定义当前点亮的导航下标
          let navIndex = 0
          for(let n = 0; n < offsetTopArr.length; n++){
              // 如果 scrollTop 大于等于第 n 个元素的 offetTop 则说明 n-1 的内容完全不可见
              // 那么此时导航索引就应该事 n 了
              if(scrollTop >= offsetTopArr[n]){
                  navIndex = n
              }
          }
          // 赋值
          this.active = navIndex
      },
      // 跳转到指定的索引元素
      scrollTo(index) {
          // 获取目标 offetTop css 选择器是从 1 开始计数，我们是从 0 开始， 所以要 +1
          const targetOffetTop = document.querySelector(`.content div:nth-child(${index + 1})`).offsetTop
          // 获取当前offetTop
          let scrollTop = document.documentElement.scrollTop || document.body.scrollTop

          // 定义一次跳 50 像素
          const STEP = 50

          // 判断往上滑还是往下滑
          if(scrollTop > targetOffetTop){
              // 往上滑
              smoothUp()
          }else{
              // 往下滑
              smoothDwon()
          }

          // 定义往下滑函数
          function smoothDwon() {
              if(scrollTop < targetOffetTop){
                // 如果和目标相差距离大于等于 STEP 就跳 STEP
                // 否则直接跳到目标点，目标是为了防止跳过了。
                  if(targetOffetTop - scrollTop >= STEP){
                      scrollTop += STEP
                  }else{
                      scrollTop = targetOffetTop
                  }
                  document.body.scrollTop = scrollTop
                  document.documentElement.scrollTop = scrollTop

                // 屏幕在绘制下一帧时会回调传给 requestAnimationFrame 的函数
                // 关于 requestAnimationFrame 可以自己查一下，在这种场景下，相比 setInterval 性价比更高
                  requestAnimationFrame(smoothDwon)
              }
          }
          // 定义往上滑函数
          function smoothUp(){
              if(scrollTop > targetOffetTop){
                  if(scrollTop - targetOffetTop >= STEP){
                      scrollTop -= STEP
                  }else{
                      scrollTop = targetOffetTop
                  }
                  document.body.scrollTop = screenTop
                  document.documentElement.scrollTop = scrollTop

                  requestAnimationFrame(smoothUp)
              }
          }
      }
  },
  mounted() {
      // 监听滚动事件
      window.addEventListener('scroll', this.onScroll)
  },
  destroyed() {
      // 必须移除监听器，不然当该vue组件被销毁了，监听器还在会出错
      window.removeEventListener('scroll', this.onScroll)
  }
  
}
</script>

<style scoped>
  /* 内容区的样式 */
  .content {
    background-color: white;
    width: 500px;
  }
  .content div {
    width: 100%;
    height: 600px;
    font-size: 36px;
    padding: 20px;
    background-color: #7ec384;
  }
  .content div:nth-child(2n) {
    background-color: #847ec3;
  }
  /* 导航栏的样式 */
  .navs {
    position: fixed;
    top: 80px;
    left: 700px;
    background-color: #efefef;
  }
  .navs li {
    padding: 0 20px;
    line-height: 1.6;
    font-size: 24px;
  }
  /* 当导航被点亮后改变颜色 */
  .navs .active{
    color: #847ec3;
    background-color: #e2e2e2;
  }
</style>